package br.com.toscano.contpedido.view;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;

import br.com.toscano.contpedido.business.ClienteBC;
import br.com.toscano.contpedido.business.PedidoBC;
import br.com.toscano.contpedido.business.RecebimentoBC;
import br.com.toscano.contpedido.domain.Cliente;
import br.com.toscano.contpedido.domain.Pedido;
import br.com.toscano.contpedido.domain.Recebimento;
import br.com.toscano.contpedido.domain.StatusPedido;
import br.com.toscano.contpedido.view.converter.DateConverter;
import br.gov.frameworkdemoiselle.annotation.NextView;
import br.gov.frameworkdemoiselle.annotation.PreviousView;
import br.gov.frameworkdemoiselle.stereotype.ViewController;
import br.gov.frameworkdemoiselle.template.AbstractListPageBean;
import br.gov.frameworkdemoiselle.transaction.Transactional;


@ViewController
@NextView("./cliente_extrato.jsf")
@PreviousView("./cliente_extrato.jsf")
public class ClienteExtratoMB extends AbstractListPageBean<Pedido, Long> {

	public Boolean isExibirLink(){
		if (FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("cliente") != null && this.getCliente() != null) {
			return true;
		}
		
		return false;
	}

	private static final long serialVersionUID = 1L;

	@Inject
	private PedidoBC pedidoBC;
	
	private Date dataInicial;
	private Date dataFinal;

	public BigDecimal getValorTotalExtrato() {
		BigDecimal valorSaldoAnterior = BigDecimal.ZERO;
		if (getValorSaldoAnterior() != null) {
			valorSaldoAnterior = getValorSaldoAnterior();
		}
		BigDecimal valorDiferencaPeriodo = BigDecimal.ZERO;
		if (getValorDiferencaPeriodo() != null) {
			valorDiferencaPeriodo = getValorDiferencaPeriodo();
		}
		BigDecimal retorno = valorSaldoAnterior.add(valorDiferencaPeriodo);

		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("valorTotalExtrato", retorno);
		return  retorno;
	}

	public BigDecimal getValorDiferencaPeriodo() {
			BigDecimal recebimentos =  this.getValorRecebimentos();
		if(recebimentos == null) {
			recebimentos = BigDecimal.ZERO;
		}
		BigDecimal pedidos = this.getValorPedidos();
		if(pedidos == null) {
			pedidos = BigDecimal.ZERO;
		}
		
		BigDecimal valorDiferencaPeriodo = recebimentos.subtract(pedidos);
		
		
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("valorDiferencaPeriodo", valorDiferencaPeriodo);

		return valorDiferencaPeriodo;
	}
	
	
	public BigDecimal getValorSaldoAnterior() {
		BigDecimal valorFinal = BigDecimal.ZERO;
		
		if (this.getCliente() != null) {

			if (this.getDataInicial() == null) {
				HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();    
				if (request.getParameter("dataInicial_input") != null && !"".equals(request.getParameter("dataInicial_input")))	{
					setDataInicial(DateConverter.getDate(request.getParameter("dataInicial_input")));
				}
			}

			if (this.getDataInicial() != null) {
				Calendar cal = Calendar.getInstance();
				cal.setTime(this.getDataInicial());
				cal.set(Calendar.HOUR_OF_DAY,0);
				cal.set(Calendar.MINUTE,0);
				cal.set(Calendar.SECOND,0);
				Date dataComparacao = cal.getTime();

				List<Pedido> pedidos = pedidoBC.consultarPedidos(null, null, this.getCliente(), null, null, null, null, null, null, null, null, null);
				if (pedidos != null ) {
					for (Pedido p : pedidos) {
						if(!p.getStatusPedido().getId().equals(StatusPedido.CANCELADO)  && p.getDataEntrega().getTime() < dataComparacao.getTime()){
							valorFinal = valorFinal.subtract(p.getValorTotalPedido());
						}
					}
				}

				List<Recebimento> recebimentos = recebimentoBC.consultarRecebimento(this.getCliente(), null, null, null, null);
				if (recebimentos != null) {
					for (Recebimento recebimento : recebimentos) {
						if (recebimento.getDataRecebimento().getTime() < dataComparacao.getTime()) {
							valorFinal = valorFinal.add(recebimento.getValorTotalRecebimento());
						}
					}
				}
			}
		}
		
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("valorSaldoAnterior", valorFinal);
		
		return valorFinal; 
	}

	public BigDecimal getValorSaldoAtual() {

		BigDecimal valorFinal = BigDecimal.ZERO;
		
		if (this.getCliente() != null) {


			List<Pedido> pedidos = pedidoBC.consultarPedidos(null, null, this.getCliente(), null, null,  null, null, null, null, null, null, null);
			if (pedidos != null ) {
				for (Pedido p : pedidos) {
					if(!p.getStatusPedido().getId().equals(StatusPedido.CANCELADO)){
						valorFinal = valorFinal.subtract(p.getValorTotalPedido());
					}
				}
			}

			List<Recebimento> recebimentos = recebimentoBC.consultarRecebimento(this.getCliente(), null, null, null, null);
			if (recebimentos != null) {
				for (Recebimento recebimento : recebimentos) {
					valorFinal = valorFinal.add(recebimento.getValorTotalRecebimento());
				}
			}
		}
		
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("valorSaldoAtual", valorFinal);
		
		return valorFinal; 
		
	}
	
	public BigDecimal getValorPedidos() {
		BigDecimal valorPedidos = BigDecimal.ZERO;
		if (this.getCliente() != null ) {
			List<Pedido> pedidos = this.getResultList();
			for (Pedido p : pedidos) {
				if (!p.getStatusPedido().getId().equals(StatusPedido.CANCELADO)) {
					valorPedidos = valorPedidos.add(p.getValorTotalPedido());
					
				}
			}
		}
		
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("valorPedidos", valorPedidos);

		return valorPedidos;
	}


	public BigDecimal getValorRecebimentos() {
		BigDecimal valorRecebimentos = BigDecimal.ZERO;
		if (this.getCliente() != null ) {
			this.getListaRecebimentos();
			List<Recebimento> rs = listaRecebimentos;
			for (Recebimento r : rs) {
				valorRecebimentos = valorRecebimentos.add(r.getValorTotalRecebimento());
			}
		}
		
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("valorRecebimentos", valorRecebimentos);

		return valorRecebimentos;
	}
 
	private List<Recebimento> listaRecebimentos;

	public List<Recebimento> getListaRecebimentos() {
		if (this.getCliente() != null) {
			listaRecebimentos = recebimentoBC.consultarRecebimento(this.getCliente(), null, this.getDataInicial(), null, null);
		} else {
			listaRecebimentos = new ArrayList<Recebimento>();
		}
		
		FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("recebimentos", listaRecebimentos);

		return listaRecebimentos;
	}

	public void setListaRecebimentos(List<Recebimento> listaRecebimentos) {
		this.listaRecebimentos = listaRecebimentos;
	}
	
	@Inject
	private RecebimentoBC recebimentoBC;
	


	@Inject
	private ClienteBC clienteBC;
	private List<SelectItem> clientes;
	private Long cliente;


	public List<SelectItem> getClientes() {
		clientes = new ArrayList<SelectItem>();
		List<Cliente> lista = clienteBC.findAll();
		for (Cliente obj: lista) {
			clientes.add(new SelectItem(obj.getId() , obj.getNome()));
		}
		return clientes;
	}

	public void setClientes(List<SelectItem> clientes) {
		this.clientes = clientes;
	}

	public Long getCliente() {
		return cliente;
	}

	public void setCliente(Long cliente) {
		this.cliente = cliente;
	}

	public Date getDataInicial() {
		return dataInicial;
	}

	public void setDataInicial(Date dataInicial) {
		this.dataInicial = dataInicial;
	}

	public Date getDataFinal() {
		return dataFinal;
	}

	public void setDataFinal(Date dataFinal) {
		this.dataFinal = dataFinal;
	}


	
	public void postProcessXLSRecebimentos(Object document) {
		HSSFWorkbook wb = (HSSFWorkbook) document;
		HSSFSheet sheet = wb.getSheetAt(0);
		
		/******************** HEADER **********************/		
		CellStyle headerStyle = wb.createCellStyle();
		Font headerFont = wb.createFont();
		headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
		headerFont.setColor(HSSFColor.BLUE.index);
		headerStyle.setFont(headerFont);
		headerStyle.setAlignment(CellStyle.ALIGN_CENTER);
		 
		Row headerRow = sheet.getRow(0);
		int cont = 0; 
		for (Cell cell : headerRow) {
			cell.setCellStyle(headerStyle);
			if (0 == cont) {
				cell.setCellValue("");
			} else if (cont ==1) {
				cell.setCellValue("");
			} else if (cont ==2) {
				cell.setCellValue("Nº Pedido");
			} else if (cont ==3) {
				cell.setCellValue("Cliente");
			} else if (cont ==4) {
				cell.setCellValue("Usuário");
			} else if (cont ==5) {
				cell.setCellValue("Data Cadastro");
			} else if (cont ==6) {
				cell.setCellValue("Data Previsto Entrega");
			} else if (cont ==7) {
				cell.setCellValue("Status");
			} else if (cont ==8) {
				cell.setCellValue("Total Pedido");
			}
			cont++;
		}
		
		/******************** TOTAL **********************/
		CellStyle style = wb.createCellStyle();
		Font font = wb.createFont();
		font.setBoldweight(Font.BOLDWEIGHT_BOLD);
//		font.setColor(HSSFColor.ORANGE.index); 
		style.setFont(font);
		style.setAlignment(CellStyle.ALIGN_RIGHT);
		Row totalRow = sheet.createRow(sheet.getLastRowNum()+2);
		Cell cell1 = totalRow.createCell(5);
		cell1.setCellValue("Total");
		cell1.setCellStyle(style);
		Cell cell2 = totalRow.createCell(6);
		
		BigDecimal valor = BigDecimal.ZERO;
		List<Recebimento> recebimentos = this.getListaRecebimentos();
		for (Recebimento recebimento : recebimentos) {
			valor = valor.add(recebimento.getValorTotalRecebimento());
		}
		
		cell2.setCellFormula(valor.toString());
		
		cell2.setCellStyle(style);

		//Ajuste do tamanho das colunas
		sheet.autoSizeColumn(0);
		sheet.autoSizeColumn(1);
		sheet.autoSizeColumn(2);
		sheet.autoSizeColumn(3);
		sheet.autoSizeColumn(4);
		sheet.autoSizeColumn(5);

	}

	public void postProcessXLS(Object document) {


		HSSFWorkbook wb = (HSSFWorkbook) document;
		HSSFSheet sheet = wb.getSheetAt(0);
		
		/******************** HEADER **********************/		
		CellStyle headerStyle = wb.createCellStyle();
		Font headerFont = wb.createFont();
		headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
		headerFont.setColor(HSSFColor.BLUE.index);
		headerStyle.setFont(headerFont);
		headerStyle.setAlignment(CellStyle.ALIGN_CENTER);
		 
		Row headerRow = sheet.getRow(0);
		int cont = 0; 
		for (Cell cell : headerRow) {
			cell.setCellStyle(headerStyle);
			if (0 == cont) {
				cell.setCellValue("");
			} else if (cont ==1) {
				cell.setCellValue("");
			} else if (cont ==2) {
				cell.setCellValue("Nº Pedido");
			} else if (cont ==3) {
				cell.setCellValue("Cliente");
			} else if (cont ==4) {
				cell.setCellValue("Usuário");
			} else if (cont ==5) {
				cell.setCellValue("Data Cadastro");
			} else if (cont ==6) {
				cell.setCellValue("Data Previsto Entrega");
			} else if (cont ==7) {
				cell.setCellValue("Status");
			} else if (cont ==8) {
				cell.setCellValue("Total Pedido");
			}
			cont++;
		}
		
		/******************** TOTAL **********************/
		CellStyle style = wb.createCellStyle();
		Font font = wb.createFont();
		font.setBoldweight(Font.BOLDWEIGHT_BOLD);
//		font.setColor(HSSFColor.ORANGE.index); 
		style.setFont(font);
		style.setAlignment(CellStyle.ALIGN_RIGHT);
		Row totalRow = sheet.createRow(sheet.getLastRowNum()+2);
		Cell cell1 = totalRow.createCell(6);
		cell1.setCellValue("Total");
		cell1.setCellStyle(style);
		Cell cell2 = totalRow.createCell(7);
		
		BigDecimal valor = BigDecimal.ZERO;
		List<Pedido> pedidos = this.getResultList();
		for (Pedido pedido : pedidos) {
			valor = valor.add(pedido.getValorTotalPedido());
		}
		
		cell2.setCellFormula(valor.toString());
		
		cell2.setCellStyle(style);

		//Ajuste do tamanho das colunas
		sheet.autoSizeColumn(0);
		sheet.autoSizeColumn(1);
		sheet.autoSizeColumn(2);
		sheet.autoSizeColumn(3);
		sheet.autoSizeColumn(4);
		sheet.autoSizeColumn(5);
		sheet.autoSizeColumn(6);
		sheet.autoSizeColumn(7);
	}
	
	public void filtrar() {
		super.clear();
		super.getResultList();
	}
	
	@Override
	protected List<Pedido> handleResultList() {

		List<Pedido> pedidos = new ArrayList<Pedido>();

		this.setCliente(null);

		HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();    

		if (request.getParameter("cliente") != null && !"".equals(request.getParameter("cliente")))	{
			this.setCliente(new Long(request.getParameter("cliente")));

			if (request.getParameter("dataInicial_input") != null && !"".equals(request.getParameter("dataInicial_input")))	{
				setDataInicial(DateConverter.getDate(request.getParameter("dataInicial_input")));
				FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("dataInicial", getDataInicial() );

			}

			if (request.getParameter("dataFinal_input") != null && !"".equals(request.getParameter("dataFinal_input")))	{
				setDataFinal(DateConverter.getDate(request.getParameter("dataFinal_input")));
				FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("dataFinal", getDataFinal() );
			}

			if (this.getCliente() != null) {
				
				Cliente cliente = this.clienteBC.load(this.getCliente());
				FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("cliente", cliente);

				List<Pedido> lista = pedidoBC.consultarPedidos(null, null, this.cliente, null, null, null, null, null, dataInicial, dataFinal, null, null);
				if (lista != null ) {
					for(Pedido p : lista) {
						if (!p.getStatusPedido().getId().equals(StatusPedido.CANCELADO)) {
							pedidos.add(p);
						}
					}
				}
			}
			
			FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("pedidos", pedidos);

		}

		return pedidos;
	}
	
	@Transactional
	public String deleteSelection() {
		boolean delete;
		for (Iterator<Long> iter = getSelection().keySet().iterator(); iter.hasNext();) {
			Long id = iter.next();
			delete = getSelection().get(id);
			if (delete) {
				pedidoBC.registrarCancelamento(id);
				iter.remove();
			}
		}
		return getPreviousView();
	}
	
	public void carregarPedido() {
		
	}
}